package com.zhangpingyang.jwttoken.map;

import java.io.Serializable;
import java.util.Map;
import java.util.Set;

/**
 * @Author: Zhang Pingyang
 * @Date: 2019/11/21 17:16
 */
public class MyHashMap<K, V> extends MyAbstractMap<K, V> implements MyMap<K, V>, Serializable, Cloneable {
    /**
     * The default initial capacity - MUST be a power of two
     */
    static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;
    /**
     * The maximum capacity, used if a higher value is implicitly specified
     * by either of the constructors with arguments.
     * MUST be a power of two <= 1 << 30
     */
    static final int MAXIMUM_CAPACITY = 1 << 30;
    /**
     * The load factor used when none specified in constructor.
     */
    static final float DEFAULT_LOAD_FACTOR = 0.75f;
    /**
     * An empty table instance to share when the table inflated
     */
    static final MyEntry<?, ?>[] EMPTY_TABLE = {};
    /**
     * The number of key-value mappings contains in this map
     */
    transient int size;
    /**
     * The next size value at which to resize(capacity * load factor)
     */
    int threshold;
    /**
     * The load factor for the hash table
     */
    final float loadFactor;

    transient int modCount;

    static final int ALTERNATIVE_HASHING_THRESHOLD_DEFAULT = Integer.MAX_VALUE;

    /**
     * holds values which can't be initialized until after VM is booted
     */
    private static class Holder {

        /**
         * Table capacity above which to switch to use alternative hashing.
         */
        static final int ALTERNATIVE_HASHING_THRESHOLD;

        static {
            String altThreshold = java.security.AccessController.doPrivileged(
                    new sun.security.action.GetPropertyAction(
                            "jdk.map.althashing.threshold"));

            int threshold;
            try {
                threshold = (null != altThreshold)
                        ? Integer.parseInt(altThreshold)
                        : ALTERNATIVE_HASHING_THRESHOLD_DEFAULT;

                // disable alternative hashing if -1
                if (threshold == -1) {
                    threshold = Integer.MAX_VALUE;
                }

                if (threshold < 0) {
                    throw new IllegalArgumentException("value must be positive integer.");
                }
            } catch(IllegalArgumentException failed) {
                throw new Error("Illegal value for 'jdk.map.althashing.threshold'", failed);
            }

            ALTERNATIVE_HASHING_THRESHOLD = threshold;
        }
    }

    transient int hashSeed = 0;

    public MyHashMap(int initialCapacity, float loadFactor) {
        if (initialCapacity < 0) {
            throw new IllegalArgumentException("Illegal initial capacity:" + initialCapacity);
        }
        if (initialCapacity > MAXIMUM_CAPACITY) {
            initialCapacity = MAXIMUM_CAPACITY;
        }
        if (loadFactor <= 0 || Float.isNaN(loadFactor)) {
            throw new IllegalArgumentException("Illegal load factor:" + loadFactor);
        }
        this.loadFactor = loadFactor;
        threshold = initialCapacity;
        init();
    }

    public MyHashMap(int initialCapacity) {
        this(initialCapacity, DEFAULT_LOAD_FACTOR);
    }

    public MyHashMap() {
        this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR);
    }

    public MyHashMap(Map<? extends K, ? extends V> m) {
        this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1, DEFAULT_INITIAL_CAPACITY), DEFAULT_LOAD_FACTOR);
        inflateTable(threshold);
        putAllForCreate(m);
    }

    /**
     * inflate the table
     */
    private void inflateTable(int toSize) {
        int capacity = roundUpToPowerOf2(toSize);
        threshold = (int)Math.min(capacity * loadFactor, )
    }

    private void init() {
//        this()
    }

    //    @Override
//    public Set<MyEntry<K, V>> entrySet() {
//        return null;
//    }


}
